package com.guaoran.distributed.netty.chat.processor;

import com.alibaba.fastjson.JSONObject;
import com.guaoran.distributed.netty.chat.constant.ChatConstant;
import com.guaoran.distributed.netty.chat.protocol.IMDecoder;
import com.guaoran.distributed.netty.chat.protocol.IMEncoder;
import com.guaoran.distributed.netty.chat.protocol.IMMessage;
import com.guaoran.distributed.netty.chat.protocol.IMProtocol;
import com.guaoran.distributed.netty.chat.util.DateTimeUtil;
import io.netty.channel.Channel;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.AttributeKey;
import io.netty.util.concurrent.GlobalEventExecutor;

/**
 * @Author gucheng
 * @Description 主要用于自定义协议内容的逻辑处理
 * 2019-04-19 18:31
 */
public class MessageProcessor {
    // 定义一些扩展属性
    private final AttributeKey<String> NICK_NAME = AttributeKey.valueOf("nickName");
    private final AttributeKey<String> IP_ADDRESS = AttributeKey.valueOf("ipAddress");
    private final AttributeKey<JSONObject> ATTRS = AttributeKey.valueOf("attrs");

    //记录在线用户
    private static ChannelGroup onlineUsers = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

    //自定义解码器
    private IMDecoder decoder = new IMDecoder();
    //自定义编码器
    private IMEncoder encoder = new IMEncoder();
    /**
     * 发送消息
     * @param client
     * @param message
     */
    public void sendMessage(Channel client, IMMessage message){
        sendMessage(client,encoder.encode(message));
    }
    /**
     * 发送消息
     * @param client
     * @param message
     */
    public void sendMessage(Channel client,String message){
        IMMessage request = decoder.decode(message);
        if(request == null){
            return;
        }
        String address = getAddress(client);

        //登录消息
        if(request.getCmd().equals(IMProtocol.LOGIN.getName())){
            client.attr(NICK_NAME).getAndSet(request.getSender());
            client.attr(IP_ADDRESS).getAndSet(address);
            // 添加到在线用户里
            onlineUsers.add(client);
            // 遍历所有当前用户，给其发送登录消息
            for (Channel channel : onlineUsers) {
                // 如果不是当前登录者
                if(channel != client){
                    request = new IMMessage(IMProtocol.SYSTEM.getName(), System.currentTimeMillis(),
                            onlineUsers.size(),getNickName(client)+ChatConstant.NON_LOGIN_SELF_SEND_MSG);
                }else {
                    // 如果是当前登录者
                    request = new IMMessage(IMProtocol.SYSTEM.getName(), System.currentTimeMillis(),
                            onlineUsers.size(), ChatConstant.LOGIN_SELF_SEND_MSG);
                }
                writeAndFlush(channel,request);
            }
        }else if (request.getCmd().equals(IMProtocol.CHAT.getName())){
            // 聊天消息
            for (Channel channel : onlineUsers) {
                if (channel == client){
                    request.setSender(ChatConstant.SELF_SENDER_MSG);
                }else {
                    // 给其他客户端显示当前客户端的昵称
                    request.setSender(getNickName(client));
                }
                request.setTime(System.currentTimeMillis());
                writeAndFlush(channel,request);
            }
        }else if (request.getCmd().equals(IMProtocol.FLOWER.getName())){
            // 送花
            JSONObject attrs = getAttrs(client);
            long currTime = System.currentTimeMillis();
            // 如果 扩展属性不为空，说明可能已经刷过花了
            if(attrs != null){
                long lastTime = attrs.getLongValue("lastFlowerTime");
                // 60秒内不允许重复刷花
                long sub = currTime - lastTime;
                final long millis = ChatConstant.BRUSH_FLOWERS_INTERVAL_MILLIS;
                // 如果在60s 内已经刷过了
                if(sub < millis ){
                    // 还剩秒数
                    String wait =  Math.round((millis - sub)/1000)+"";
                    request.setSender(ChatConstant.SELF_SENDER_MSG);
                    request.setCmd(IMProtocol.SYSTEM.getName());
                    request.setContent(ChatConstant.BRUSH_FLOWERS_FREQUENTLY.replace(ChatConstant.REPLACE,wait));
                    writeAndFlush(client,request);
                    return;
                }
            }

            // 还未刷过花或者已经60s内未刷花，则进行刷花
            for (Channel channel : onlineUsers) {
                if (channel == client){
                    request.setSender(ChatConstant.SELF_SENDER_MSG);
                    request.setContent("你给大家送了一波鲜花雨");
                    setAttrs(client, "lastFlowerTime", currTime);
                }else{
                    request.setSender(getNickName(client));
                    request.setContent(getNickName(client) + "送来一波鲜花雨");
                }
                request.setTime(System.currentTimeMillis());
                writeAndFlush(channel,request);
            }
        }

    }

    /**
     * 获取用户远程IP地址
     * @param client
     * @return
     */
    public String getAddress(Channel client){
        return client.remoteAddress().toString().replaceFirst("/","");
    }
    /**
     * 获取用户昵称
     * @param client
     * @return
     */
    public String getNickName(Channel client){
        return client.attr(NICK_NAME).get();
    }
    /**
     * 获取扩展属性
     * @param client
     * @return
     */
    public JSONObject getAttrs(Channel client){
        return client.attr(ATTRS).get();
    }
    /**
     * 设置扩展属性
     * @param client
     * @return
     */
    private void setAttrs(Channel client,String key,Object value){
        try{
            JSONObject json = client.attr(ATTRS).get();
            json.put(key, value);
            client.attr(ATTRS).set(json);
        }catch(Exception e){
            JSONObject json = new JSONObject();
            json.put(key, value);
            client.attr(ATTRS).set(json);
        }
    }

    /**
     * 发送到客户端
     * @param client
     * @param request
     */
    public void writeAndFlush(Channel client,IMMessage request){
        client.writeAndFlush(new TextWebSocketFrame(encoder.encode(request)));
    }
    /**
     * 登出通知
     * @param client
     */
    public void logout(Channel client) {
        //如果nickName为null，没有遵从聊天协议的连接，表示未非法登录
        if(getNickName(client) == null){
            return;
        }
        for (Channel channel : onlineUsers) {
            IMMessage request = new IMMessage(IMProtocol.SYSTEM.getName(), System.currentTimeMillis(), onlineUsers.size(), getNickName(client) + "离开");
            writeAndFlush(channel,request);
        }
        onlineUsers.remove(client);
    }
}
